﻿using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Transactions;
using System.Web;
using MMSWebsite.Models;
using MMSWebsite.Models.Asset;
using BusinessLibrary;

namespace MMSWebsite.DataAccessManagement.AssetManagement
{
    public class AssetProvider
    {
        MMSEntities _entities = new MMSEntities();
        CustomerAccessProvider _cap = new CustomerAccessProvider();
        MasterDataAccessProvider _mdap = new MasterDataAccessProvider();
        AttributeAssetProvider _atp = new AttributeAssetProvider();

        //get Assets of Customer
        public List<Asset> GetAssetsByCusid(int cusId)
        {
            var list = new List<Asset>();

            var firstOrDefault = _entities.MMS_CUSTOMERs.FirstOrDefault(x => x.Id == cusId);
            if (firstOrDefault != null)
            {
                var mmsEmpCusCtrl = firstOrDefault.MMS_EMP_CUS_CTRL.LastOrDefault(x => x.freeze == Constants.UNFREEZE && x.Status == null);
                if (mmsEmpCusCtrl != null)
                {
                    var assets =
                        mmsEmpCusCtrl.MMS_ASSET.ToList();
                    //var assets = _entities.MMS_ASSETs.Where(x => x.CusId == cusId).ToList();
                    foreach (var mmsAsset in assets)
                    {
                        list.Add(ConvertMMSAssetToModel(mmsAsset));
                    }
                }
            }

            return list;
        }

        public List<Asset> GetAssetsResultByCusid(int cusId)
        {
            var list = new List<Asset>();

            var firstOrDefault = _entities.MMS_CUSTOMERs.FirstOrDefault(x => x.Id == cusId);
            if (firstOrDefault != null)
            {
                var mmsEmpCusCtrl = firstOrDefault.MMS_EMP_CUS_CTRL.LastOrDefault(x => x.freeze == Constants.UNFREEZE && x.Status != null);
                if (mmsEmpCusCtrl != null)
                {
                    var assets =
                        mmsEmpCusCtrl.MMS_ASSET.ToList();
                    //var assets = _entities.MMS_ASSETs.Where(x => x.CusId == cusId).ToList();
                    foreach (var mmsAsset in assets)
                    {
                        list.Add(ConvertMMSAssetToModel(mmsAsset));
                    }
                }
            }

            return list;
        }
        /// <summary>
        /// Get Asset By Id
        /// <para>Return: Asset</para>
        /// <para>Caution: Can Be Null</para>
        /// </summary>
        /// <param name="assId">Asset Id</param>
        /// <returns>Asset</returns>
        public Asset GetAssetById(int assId)
        {
            try
            {
                Asset asset = null;
                var mmsAssets = _entities.MMS_ASSETs.Where(x => x.id == assId);
                if (mmsAssets == null)
                {
                    return null;
                }
                foreach (var a in mmsAssets)
                {
                    asset = ConvertMMSAssetToModel(a);
                    break;
                }
                return asset;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        //Add new Asset
        public void AddAsset(Asset asset)
        {
            using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
            {
                try
                {
                    var caseEmp = _entities.MMS_EMP_CUS_CTRLs.Where(x => x.idCus == asset.Customer.Id && x.Status == null).ToList();
                    int caseId = caseEmp.LastOrDefault().id;
                    var mmsAsset = new MMS_ASSET
                                       {
                                           CaseId = caseId,
                                           AssetName = asset.AssetName,
                                           AssetType = asset.AssetType.id,
                                           Information = asset.Information
                                       };

                    //Add begin status = "New"
                    mmsAsset.MMS_ASSET_STATUS.Add(new MMS_ASSET_STATUS
                                                      {
                                                          Status =
                                                              _mdap.GetMDByCodeAndType(Constants.STR_STATUS,
                                                                                       Constants.STR_TYPE_STATUS_NEW)[0].id
                                                      });


                    //initialize new valuation for this asset
                    mmsAsset.MMS_VALUATION.Add(new MMS_VALUATION());

                    //initialize new RAte for this asset
                    mmsAsset.MMS_RATE.Add(new MMS_RATE());

                    //initialize new Loan for this asset
                    mmsAsset.MMS_LOAN.Add(new MMS_LOAN());
                    //phải initialize các giá trị Valuation, Loan, Rate (mặc dù null) 
                    //để có thể lấy giá trị toàn bộ Asset khi chưa đc Valuated or Loaned mà không báo lỗi 

                    _entities.MMS_ASSETs.AddObject(mmsAsset);
                    _entities.SaveChanges();
                    ts.Complete();
                }
                catch (Exception ex)
                {
                    ts.Dispose();
                    throw new Exception(ex.Message);
                }
            }

        }

        /// <summary>
        /// Edit Asset With Relevant Customer By Employee Loging In
        /// </summary>
        /// <param name="asset">Asset</param>
        /// <param name="evm">Employee View Model</param>
        public void EditAsset(Asset asset, EmployeeViewModel evm)
        {
            bool isModified = false;
            using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
            {
                try
                {
                    var mmsAsset = _entities.MMS_ASSETs.FirstOrDefault(x => x.id == asset.Id);
                    mmsAsset.AssetName = asset.AssetName;
                    mmsAsset.AssetType = asset.AssetType.id;
                    mmsAsset.Information = asset.Information;
                    // Get Relevant Role

                    //every employeeViewModel has all general roles: any roles has RoleIschecked = true -> this emp has this role
                    //Get Role of user by using lambda to filter any role has RoleIschecked = true
                    foreach (RoleWrapper rw in evm.Roles.Where(x=>x.RoleIsChecked))
                    {
                        // Each Employee Has Only One Role
                        if (isModified)
                        {
                            break;
                        }
                        switch (rw.Role.RoleName)
                        {
                            case Constants.FV_ROLE:
                                {
                                    //Add begin status = "New"

                                    if (asset.Valuation.Value != null)
                                    {
                                        //add new row in MMS_ASSET_STATUS with value = EVALUATED by FV
                                        mmsAsset.MMS_ASSET_STATUS.Add(new MMS_ASSET_STATUS
                                                                          {
                                                                              Status =
                                                                                  _mdap.GetMDByCodeAndType(
                                                                                      Constants.STR_STATUS,
                                                                                      Constants.
                                                                                          STR_TYPE_STATUS_EVALUATED)
                                                                                  [0].id
                                                                          });

                                        //Edit valuation for this asset (not insert new row)
                                        var mmsVal = mmsAsset.MMS_VALUATION.Last();
                                        mmsVal.ValuationBy = evm.Employee.Id;
                                        mmsVal.Value = asset.Valuation.Value;
                                        mmsVal.ValuationDate = DateTime.Now;
                                        mmsVal.Freeze = Constants.UNFREEZE;
                                        
                                        break;
                                    }
                                    else continue;

                                }
                            case Constants.REVIEWER_ROLE:
                                {
                                    //Add begin status = "New"
                                    if (asset.Rate.ValueRate != null && asset.Loan.ValueLoan != null)
                                    {
                                        //add new row in MMS_ASSET_STATUS with value = LOAN by FV
                                        mmsAsset.MMS_ASSET_STATUS.Add(new MMS_ASSET_STATUS
                                                                          {
                                                                              Status =
                                                                                  _mdap.GetMDByCodeAndType(
                                                                                      Constants.STR_STATUS,
                                                                                      Constants.STR_TYPE_STATUS_LOAN)[0]
                                                                                  .id
                                                                          });

                                        //Edit rate for this asset (not insert new row)
                                        var mr = mmsAsset.MMS_RATE.Last();
                                        mr.CreateUid = evm.Employee.Id;
                                        mr.Rate = asset.Rate.ValueRate;
                                        mr.RateDate = DateTime.Now;
                                        mr.Freeze = Constants.UNFREEZE;
                                        mmsAsset.MMS_RATE.Add(mr);

                                        //Edit loan for this asset (not insert new row)
                                        var ml = mmsAsset.MMS_LOAN.Last();
                                        ml.LoanBy = evm.Employee.Id;
                                        ml.ValueLoan = asset.Loan.ValueLoan;
                                        ml.LoanDate = DateTime.Now;
                                        ml.Freeze = Constants.UNFREEZE;
                                    }
                                    break;
                                }
                            default: // Admin. Can not edit Valuation, Loan, Rate. If he wants to edit, he must login in FV or Reviewer Role
                                {
                                    break;
                                }
                        }
                    }
                    _entities.SaveChanges();
                    ts.Complete();
                }
                catch (Exception ex)
                {
                    ts.Dispose();
                }
            }

        }

        public void UpdateStatusCase(int assetId, string status)
        {

            var asset = _entities.MMS_ASSETs.FirstOrDefault(x => x.id == assetId);
            int caseId;
            if (asset != null)
            {
                caseId = (int) asset.CaseId;
                var mmsCusEmp = _entities.MMS_EMP_CUS_CTRLs.Single(x => x.id == caseId);
                var masterStatus = _mdap.GetMDByCodeAndType(Constants.STR_STATUS, status).Single();
                mmsCusEmp.Status = masterStatus.id;
                _entities.SaveChanges();
            }

        }

        //Update status
        public void UpdateStatus(int assetId, string status)
        {
            var mmsasset = _entities.MMS_ASSETs.FirstOrDefault(x => x.id == assetId);
            if(mmsasset!=null)
            {
                mmsasset.MMS_ASSET_STATUS.Add(new MMS_ASSET_STATUS
                                                  {
                                                      Status =
                                                          _mdap.GetMDByCodeAndType(
                                                              Constants.STR_STATUS,
                                                              status)
                                                          [0].id
                                                  });
            }
            _entities.SaveChanges();
        }

        //Reset Asset when Reviewer Remove Responsibility of a Customer
        public void ResetAsset(int assetId)
        {
            var mmsasset = _entities.MMS_ASSETs.FirstOrDefault(x => x.id == assetId);
            //Reset null to Valuation
            var mav = mmsasset.MMS_VALUATION.FirstOrDefault();
            mav.ValuationDate = null;
            mav.ValuationBy = null;
            mav.Value = null;

            //Reset null to Loan
            var mal = mmsasset.MMS_LOAN.FirstOrDefault();
            mal.ValueLoan = null;
            mal.LoanBy = null;
            mal.LoanDate = null;

            //Reset null to Rate
            var mar = mmsasset.MMS_RATE.FirstOrDefault();
            mar.Rate = null;
            mar.RateDate = null;
            mar.CreateDate = null;

            //Reset Status -> NEW
            mmsasset.MMS_ASSET_STATUS.Add(new MMS_ASSET_STATUS
                                              {
                                                  Status =
                                                      _mdap.GetMDByCodeAndType(Constants.STR_STATUS,
                                                                               Constants.STR_TYPE_STATUS_NEW)[0].id
                                              });

            _entities.SaveChanges();
        }

        //Convert Type MMS_ASSET to Asset Model
        public Asset ConvertMMSAssetToModel(MMS_ASSET mmsasset)
        {
            var asset = new Asset();

            asset.Id = mmsasset.id;
            asset.Customer = _cap.GetCusById((int) mmsasset.MMS_EMP_CUS_CTRL.idCus);
            asset.AssetName = mmsasset.AssetName;
            asset.Information = mmsasset.Information;
            asset.AssetType = _mdap.GetMDById((int) mmsasset.AssetType);
            asset.Status = _atp.GetStatusByAssetId(mmsasset.id);
            asset.Valuation = _atp.GetValuationByAssetId(mmsasset.id).Last();
            asset.Rate = _atp.GetRatesByAssetId(mmsasset.id)[0];
            asset.Loan = _atp.GetLoansByAssetId(mmsasset.id)[0];
            asset.Freeze = mmsasset.Freeze;
            return asset;

        }

        public List<MMS_ASSET_STATUS> GetAssetStatusListByRole(Asset asset, string roleName)
        {
            List<MMS_ASSET_STATUS> lsAssStaOut = null;
            List<AssetStatus> lsAssStaModelInput = null;
            List<MasterData> lsMasterData = null;
            try
            {
                // Get All Asset Status In Master Data
                lsMasterData = _mdap.GetMDByCode(Constants.STR_STATUS);

                if (lsMasterData != null)
                {
                    // Get All Asset Status Changed In Current Asset
                    lsAssStaModelInput = asset.Status;
                    // If No Any Status In Current Asset, Pass NEW Status For Current Asset
                    if (lsAssStaModelInput == null)
                    {
                        lsAssStaOut = new List<MMS_ASSET_STATUS>();
                        lsAssStaOut.Add(new MMS_ASSET_STATUS
                        {
                            Status = lsMasterData.Find(x => x.code.Equals(Constants.STR_STATUS)
                                && x.type.Equals(Constants.STR_TYPE_STATUS_NEW)).id
                        });
                    }
                    else
                    {
                        foreach (AssetStatus assSta in lsAssStaModelInput) 
                        {
                            foreach (MasterData md in lsMasterData)
                            {
                                if (md.id != assSta.Id)
                                {
                                    switch (roleName)
                                    {
                                        case Constants.FV_ROLE:
                                            {
                                                break;
                                            }
                                        case Constants.REVIEWER_ROLE:
                                            {
                                                break;
                                            }
                                    }
                                    lsAssStaOut.Add(new MMS_ASSET_STATUS { Status = md.id });
                                }
                            }
                        }
                    }
                }
                return lsAssStaOut;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }
}